package org.zebra.web.annotation.version;

import cn.hutool.core.text.CharSequenceUtil;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 接口版本控制
 *
 * @author zhanghongbin
 */
public class ApiVersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

    @Override
    protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
        return this.buildApiVersionRequestCondition(apiVersion);
    }

    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
        return this.buildApiVersionRequestCondition(apiVersion);
    }

    private ApiVersionRequestCondition buildApiVersionRequestCondition(ApiVersion apiVersion) {
        if (apiVersion != null) {
            ApiVersionVO apiVersionVO = ApiVersionConverter.convert(apiVersion);
            if (apiVersionVO != null) {
                return new ApiVersionRequestCondition(apiVersionVO);
            }
        }
        return null;
    }

    private final Pattern versionPattern = Pattern.compile("\\{[^}(?!{)]*\\}");

    /**
     * 动态给访问地址增加版本号
     * <p>
     * 规则为:在方法注解 RequestMapping 路径前边增加 /{version}
     *
     * @param method 方法对象
     * @param handlerType 类型
     * @return 对象
     */
    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo info = super.getMappingForMethod(method, handlerType);
        if (info != null) {
            RequestCondition requestCondition = info.getCustomCondition();
            if (requestCondition != null && (requestCondition instanceof ApiVersionRequestCondition)) {
                RequestMapping requestMapping = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
                Set<String> tempPatternPath = new LinkedHashSet<>();
                Set<String> currentPatternPath = info.getPatternsCondition().getPatterns();
                tempPatternPath.addAll(currentPatternPath);
                currentPatternPath.clear();
                String[] apiPath = this.getApiPath(method, handlerType);
                // 如果类上存在RequestMapping
                if (requestMapping != null) {
                    String[] values = requestMapping.value();
                    for (String v : values) {
                        for (String patternPath : tempPatternPath) {
                            Matcher matcher = versionPattern.matcher(v);
                            String path = "";
                            if (matcher.find()) {
                                String versionPlaceholder = matcher.group();
                                String methodPath = CharSequenceUtil.removePreAndLowerFirst(patternPath, v);
                                if (versionPlaceholder.equals("{version}")) {
                                    v = v.replaceAll("/\\{version\\}", apiPath[1]);
                                    path = apiPath[0] + v + methodPath;
                                } else {
                                    path = apiPath[0] + v + apiPath[1] + methodPath;
                                }
                            } else {
                                String methodPath = patternPath.replaceFirst(v, "");
                                path = apiPath[0] + v + apiPath[1] + methodPath;
                            }
                            currentPatternPath.add(path);
                        }
                    }
                } else {
                    for (String patternPath : tempPatternPath) {
                        String path = apiPath[0] + apiPath[1] + patternPath;
                        currentPatternPath.add(path);
                    }
                }
                // 实现版本继承
                //                String apiTypeName = this.getApiTypeName(method, handlerType);
                //                //如果类上存在RequestMapping
                //                if (requestMapping != null) {
                //                    String[] values = requestMapping.value();
                //                    for (String v : values) {
                //                        for (String patternPath : tempPatternPath) {
                //                            String methodPath = patternPath.replaceAll(v, "");
                //                            String path = apiTypeName + v + "/{version}" + methodPath;
                //                            currentPatternPath.add(path);
                //                        }
                //                    }
                //                } else {
                //                    for (String patternPath : tempPatternPath) {
                //                        String path = "/{version}" + patternPath;
                //                        currentPatternPath.add(path);
                //                    }
                //                }
                //
            }
        }
        return info;
    }

    private String[] getApiPath(Method method, Class<?> handlerType) {
        String apiTypePath = "/";
        String aipVersionPath = "/v";
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
        if (apiVersion != null) {
            apiTypePath = apiTypePath + apiVersion.type().getName();
            aipVersionPath = aipVersionPath + apiVersion.value();
        } else {
            apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
            if (apiVersion != null) {
                apiTypePath = apiTypePath + apiVersion.type().getName();
                aipVersionPath = aipVersionPath + apiVersion.value();
            }
        }
        if (apiTypePath.equals("/")) {
            apiTypePath = "";
        }
        return new String[] {apiTypePath, aipVersionPath};
    }

    //    private String getApiTypeName(Method method, Class<?> handlerType) {
    //        String apiTypeName = "/";
    //        ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
    //        if (apiVersion != null) {
    //            if (!apiVersion.type().getName().equals("")) {
    //                apiTypeName = apiTypeName + apiVersion.type().getName();
    //            }
    //        }
    //        if (apiTypeName.equals("/")) {
    //            apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
    //            if (apiVersion != null) {
    //                apiTypeName = apiTypeName + apiVersion.type().getName();
    //            } else {
    //                apiTypeName = "";
    //            }
    //        }
    //        return apiTypeName;
    //    }

    //    /**
    //     * 判断是否版本过期
    //     *
    //     * @param info
    //     * @param lookupPath
    //     * @param request
    //     * @see ApiVersionRequestCondition#getMatchingCondition 方法执行完成后调用
    //     */
    //    @Override
    //    protected void handleMatch(RequestMappingInfo info, String lookupPath, HttpServletRequest request) {
    //        RequestCondition requestCondition = info.getCustomCondition();
    //        if (requestCondition != null && requestCondition instanceof ApiVersionRequestCondition) {
    //            ApiVersionRequestCondition apiVersionRequestCondition = (ApiVersionRequestCondition) requestCondition;
    //            if (apiVersionRequestCondition.getApiVersionVO().getApiVersion().deprecated()) {
    //                throw new ResultException(StatusCode.API_VERSION_DEPRECATED.getCode(),
    // StatusCode.API_VERSION_DEPRECATED.getMsg());
    //            }
    //        }
    //        super.handleMatch(info, lookupPath, request);
    //    }

}
